/*
 * Copyright(c)2018,2024,guowenmeng24@163.comAllrightsreserved.
 */
package com.bkhech.home.practice.javacore.fileupload;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;
import java.util.StringJoiner;

/**
 * FileWorker
 *
 * @author guowm
 * @date 2024/07/02
 */
@Slf4j
public class FileWorker implements Runnable {
    final FileMetadata metadata;

    public FileWorker(FileMetadata metadata) {
        this.metadata = metadata;
    }

    @Override
    public void run() {
        // 线程具体要做的事情
        try (RandomAccessFile in = new RandomAccessFile(metadata.getSrc(), "r");
             RandomAccessFile out = new RandomAccessFile(metadata.getDestTmp(), "rw")) {

            System.out.println("线程开始执行" + metadata.getFileIndex());

            final Long part = metadata.getPart();
            final Map<Integer, Long> processMap = metadata.getProcess();
            final String[] logData = metadata.getLogData();
            final int fileIndex = metadata.getFileIndex();
            final long hasUploadBytes = getUploadedBytes(logData, fileIndex);
            // 从指定位置读
            in.seek(hasUploadBytes);
            out.seek(hasUploadBytes);

            byte[] bytes = new byte[1024 * 10];
            int len, plen = 0;

            while (true) {
                len = in.read(bytes);
                if (len == -1) {
                    break;
                }
                // 如果不等于 -1 ， 则 累加求和
                plen += len;

                // 将读取的字节数，放入 到 map 中
                processMap.put(fileIndex, plen + hasUploadBytes);

                // 将读取到的数据、进行写入
                out.write(bytes, 0, len);

                // 将当前读取进度数据进行写入文件中
                logFileWrite(metadata, processMap);

                if (plen + hasUploadBytes >= (fileIndex + 1) * part) {
                    break;
                }
            }
        } catch (Exception e) {
            log.info(e.getMessage());
        }
    }

    /**
     * 将当前读取进度数据进行写入文件中
     *
     * @param metadata
     * @param processMap
     */
    private static void logFileWrite(FileMetadata metadata, Map<Integer, Long> processMap) {
        try (RandomAccessFile logFile = new RandomAccessFile(metadata.getLogName(), "rw")) {
            // 直接覆盖全部文件
            logFile.seek(0);
            StringJoiner joiner = new StringJoiner(",");
            processMap.forEach((key, val) -> joiner.add(java.lang.String.valueOf(val)));
            logFile.write(joiner.toString().getBytes(StandardCharsets.UTF_8));
        } catch (IOException e) {
            log.info(e.getMessage());
        }
    }

    private static long getUploadedBytes(String[] logData, int fileIndex) {
        long hasUploadBytes = 0;
        if (Objects.nonNull(logData)) {
            try {
                hasUploadBytes = Long.parseLong(logData[fileIndex]);
            } catch (Exception e) {
                log.info(e.getMessage());
            }
        }
        return hasUploadBytes;
    }
}